/*
* Copyright (c) 2006, obsoleet industries
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of obsoleet industries nor the names of its
*       contributors may be used to endorse or promote products derived from
*       this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


using libsecondlife;
using libsecondlife.Packets;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Meebey.SmartIrc4net;
using System.IO;

namespace slirc
{
    partial class SlircNG
    {
/*        void textOut(string text)
        {
            if (myClient.IsConnected)
            {
                myClient.SendMessage(SendType.Message, ircChannel, text);
            }
            Console.WriteLine(text);
            if (Client.Network.Connected)
            {
                Client.Self.Chat(text, 0, MainAvatar.ChatType.Say);
            }
        }*/
        void textOut(string text, bool console, bool irc_chan, bool sl_chat)
        {
            if (myClient.IsConnected && irc_chan)
            {
                myClient.SendMessage(SendType.Message, ircChannel, text);
            }
            if (console)
            {
                Console.WriteLine(text);
            }
            if (Client.Network.Connected && sl_chat)
            {
                Client.Self.Chat("[slirc]!@#" + text, 4312, MainAvatar.ChatType.Say);
            }
        }
        bool readConfig(string configFile)
        {
            try
            {
                using (StreamReader sr = new StreamReader(configFile))
                {
                    String line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        #region irc_server
                        if (line.Contains("irc_server="))
                        {
                            ircServer = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Read in IRC Server " + ircServer, 5);
                        }
                        #endregion
                        #region irc_channel
                        else if (line.Contains("irc_channel="))
                        {
                            ircChannel = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Read in IRC Channel " + ircChannel, 5);
                        }
#endregion
                        #region irc_nick
                        else if (line.Contains("irc_nick="))
                        {
                            myNick = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Read in IRC Nick " + ircServer, 5);
                        }
#endregion
                        #region first_name
                        else if (line.Contains("first_name="))
                        {
                            firstName = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Read in SL First Name " + firstName, 5);
                        }
#endregion
                        #region last_name
                        else if (line.Contains("last_name="))
                        {
                            lastName = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Read in SL Last Name " + lastName, 5);
                        }
#endregion
                        #region sl_password
                        else if (line.Contains("sl_password="))
                        {
                            password = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Read in SL password " + password, 5);
                        }
#endregion
                        #region sl_master
                        else if (line.Contains("sl_master="))
                        {
                            try
                            {
                                string key = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                                masterSL = (LLUUID)key;
                                debug("Read in SL Master Key " + masterSL.ToString(), 5);
                            }
                            catch 
                            {
                                debug("sl_master config option must specify a valid LLUUID", 1);
                                return false;
                            }
                        }
#endregion
                        #region irc_master
                        else if (line.Contains("irc_master="))
                        {
                            masterIrc = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Read in IRC Master Hostmask " + masterIrc);
                        }
                        #endregion
                        #region home_pos
                        else if (line.Contains("home_pos="))
                        {
                            string message = line.Substring(line.IndexOf("=" )+ 1, line.Length - line.IndexOf("=") - 1);
                            char[] splitChar = { ',' };
                            string[] msg = message.Split(splitChar);
                            try
                            {
                                campPosition homePos = new campPosition();
                                homePos.name = "home";
                                homePos.pos = new LLVector3(float.Parse(msg[1]), float.Parse(msg[2]), float.Parse(msg[3]));
                                homePos.sim = msg[0];
                                homePos.key = new LLUUID(msg[4]);
                                camps.Clear();
                                camps.Add(homePos);
                                debug("Read in home (camps wiped) - " + camps[0].sim + "@" + camps[0].pos.ToString() + " on " + camps[0].key.ToString(), 5);
                            }
                            catch 
                            {
                                debug("Syntax error : home_pos=sim name,x,y,z,key", 1);
                                return false;
                            }
                        }
#endregion
                        #region debug_level
                        else if (line.Contains("debug_level="))
                        {
                            try
                            {
                                debugLevel = int.Parse(line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1));
                                debug("Read in debug level - " + debugLevel.ToString());
                            }
                            catch
                            {
                                debug("Syntax error : debugLevel=[1-5]", 1);
                                return false;
                            }
                        }
#endregion
                        #region debug_irc
                        else if (line.Contains("debug_irc="))
                        {
                            try
                            {
                                debugIrc = bool.Parse(line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1));
                                debug("Read in debug to IRC setting - " + debugIrc.ToString(), 5);
                            }
                            catch
                            {
                                debug("Syntax error : debug_irc=[true|false]", 1);
                                return false;
                            }
                        }
#endregion
                        #region debug_sl
                        else if (line.Contains("debug_sl="))
                        {
                            try
                            {
                                debugChat = bool.Parse(line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1));
                                debug("Read in debug to SL setting - " + debugChat.ToString(), 5);
                            }
                            catch
                            {
                                debug("Syntax error : debug_sl=[true|false]", 1);
                                return false;
                            }
                        }
#endregion
                        #region debug_console
                        else if (line.Contains("debug_console="))
                        {
                            try
                            {
                                debugConsole = bool.Parse(line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1));
                                debug("Read in debug to console setting - " + debugConsole.ToString(), 5);
                            }
                            catch
                            {
                                debug("Syntax error : debug_console=[true|false]", 1);
                                return false;
                            }
                        }
#endregion
                        #region acl_file
                        if (line.Contains("acl_file="))
                        {
                            aclFile = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Read in ACL File " + aclFile, 5);
                        }
#endregion
                        #region camp_file
                        if (line.Contains("camp_file="))
                        {
                            campFile = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Read in Camps File " + campFile, 5);
                        }
#endregion
                        #region relay
                        else if (line.Contains("relay="))
                        {
                            try
                            {
                                relayChat = bool.Parse(line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1));
                                debug("Read in relay setting - " + relayChat.ToString(), 5);
                            }
                            catch
                            {
                                debug("Syntax error : relay=[true|false]", 1);
                                return false;
                            }
                        }
                                                #endregion
                        #region relay_sl
                        else if (line.Contains("relay_sl="))
                        {
                            try
                            {
                                relaySL = bool.Parse(line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1));
                                debug("Read in relay (SL) setting - " + relaySL.ToString(), 5);
                            }
                            catch
                            {
                                debug("Syntax error : relay_sl=[true|false]", 1);
                                return false;
                            }
                        }
                                                #endregion
                        #region relay_irc
                        else if (line.Contains("relay_irc="))
                        {
                            try
                            {
                                relayIRC = bool.Parse(line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1));
                                debug("Read in relay (IRC) setting - " + relayIRC.ToString(), 5);
                            }
                            catch
                            {
                                debug("Syntax error : relay_irc=[true|false]", 1);
                                return false;
                            }
                        }
                        #endregion
                        #region uniquenick
                        else if (line.Contains("uniquenick="))
                        {
                            try
                            {
                                uniqueIRCNick = bool.Parse(line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1));
                                debug("Read in unique nick setting - " + uniqueIRCNick.ToString(), 5);
                            }
                            catch
                            {
                                debug("Syntax error : uniquenick=[true|false]", 1);
                                return false;
                            }
                        }
                        #endregion
                    }
                }
                return true;
            }
            catch (FileNotFoundException e)
            {
                // Let the user know what went wrong.
                debug("File Error - " + e.Message.ToString(), 1);
                return false;
            }
            catch (FileLoadException e)
            {
                debug("File Error - " + e.Message.ToString(), 1);
                return false;
            }
        }
        bool readCamps(string configFile)
        {
            camps.Clear();
            try
            {
                using (StreamReader sr = new StreamReader(configFile))
                {
                    String line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        if (line.Contains("camp="))
                        {
                            string message = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            char[] splitChar = { ',' };
                            string[] msg = message.Split(splitChar);
                            try
                            {
                                campPosition thisCamp = new campPosition();
                                thisCamp.name = msg[0];
                                thisCamp.pos = new LLVector3(float.Parse(msg[2]), float.Parse(msg[3]), float.Parse(msg[4]));
                                thisCamp.sim = msg[1];
                                thisCamp.key = new LLUUID(msg[5]);
                                camps.Add(thisCamp);
                                debug("Read in " + thisCamp.name +" - " + thisCamp.sim + "@" + thisCamp.pos.ToString() + " on " + thisCamp.key.ToString(), 5);
                            }
                            catch
                            {
                                debug("Syntax error : camp=name,sim name,x,y,z,key", 1);
                            }
                        }
                    }
                }
                return true;
            }
            catch (Exception e)
            {
                // Let the user know what went wrong.
                debug("Camp file could not be read", 1);
                debug(e);
                    
                return false;
            }
        }
        bool readAcl(string configFile)
        {
            allowedIrc.Clear();
            allowedSL.Clear();
            try
            {
                using (StreamReader sr = new StreamReader(configFile))
                {
                    String line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        if (line.Contains("irc="))
                        {
                            string message = line.Substring(line.IndexOf("=") + 1, line.Length - line.IndexOf("=") - 1);
                            debug("Added " + message + " to IRC ACL", 4);
                            allowedIrc.Add( message);
                        } else if (line.Contains("sl="))
                        {
                            string message = line.Substring(line.IndexOf("=" )+ 1, line.Length - line.IndexOf("=") - 1);
                            debug("Added " + message + " to SL ACL", 4);
                            allowedSL.Add(message);
                        }
                    }
                }
                return true;
            }
            catch
            {
                // Let the user know what went wrong.
                debug("Camp file could not be read", 1);
                return false;
            }
        }
        bool writeCamp(string configFile)
        {
            try
            {
                using (StreamWriter sw = new StreamWriter(configFile))
                {
                    foreach (campPosition thisCamp in camps)
                    {
                        sw.WriteLine("camp=" + thisCamp.name + "," + thisCamp.sim + "," + thisCamp.pos.X.ToString() + "," + thisCamp.pos.Y.ToString() + "," + thisCamp.pos.Z.ToString() + "," + thisCamp.key.ToString());
                    }
                    sw.Close();
                }
                return true;
            }
            catch
            {
                debug("Error writing to ACL File", 1);
                return false;
            }
        }
        bool writeAcl(string configFile)
        {
            try
            {
                using (StreamWriter sw = new StreamWriter(configFile))
                {
                    foreach (string thisLine in allowedIrc)
                    {
                        sw.WriteLine("irc=" + thisLine);
                    }
                    foreach (LLUUID thisLine in allowedSL)
                    {
                        sw.WriteLine("sl=" + thisLine.ToString());
                    }
                    sw.Close();
                }
                return true;
            }
            catch
            {
                debug("Error writing to ACL File", 1);
                return false;
            }
        }
        //error - warning - info - notice - debug
        void debug(string message, int level, bool console, bool irc, bool chat)
        {
            if (Debug && level <= debugLevel )
            {
                string output = null;
                if (level == 3)
                {
                    output = "[INFO]";
                }
                else if (level == 4)
                {
                    output = "[NOTICE]";
                }
                else if (level == 2)
                {
                    output = "[WARNING]";
                }
                else if (level == 1)
                {
                    output = "[ERROR]";
                }
                else if (level == 5)
                {
                    output = "[DEBUG]";
                }
                output = output + " " + message;
                if (console)
                {
                    Console.WriteLine(output);
                }
                if (irc && myClient.IsConnected)
                {
                    myClient.SendMessage(SendType.Message, ircChannel, output);
                }
                if (chat && Client.Network.Connected)
                {
                    Client.Self.Chat("[slirc-ng]>!@#" + output, 4312, MainAvatar.ChatType.Say);
                }
            }
        }
        void debug(string message, int level)
        {
            debug(message, level, debugConsole, debugIrc, debugChat);
        }
        void debug(string message)
        {
            debug(message, 5, debugConsole, debugIrc, debugChat);
        }
        void debug(Exception e)
        {
            debug("[EX] " + e.Message + " @ " + e.StackTrace.ToString());
        }
        bool camp(string name)
        {
            commandStand();
            campCheckTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            foreach ( campPosition thisCamp in camps ) {
                debug("Checking camp " + thisCamp.name + " against " + name, 5);
                if (thisCamp.name == name)
                {
                    debug("Camping at " + name, 3);
                    Client.Self.Teleport(thisCamp.sim, thisCamp.pos);
                    for ( int i = 0; i < 5 ; i++ ) {
                        if ( teleportEvent.WaitOne( 100, false ) ) {
                            break;
                        }
                    }
                    teleportEvent.Reset();
                    for (int i = 0; i < 30; i++)
                    {
                        debug("Current Sim - " + Client.Network.CurrentSim.Region.Name + " Camp Sim " + thisCamp.sim);
                        if (Client.Network.CurrentSim.Region.Name.ToLower() == thisCamp.sim.ToLower()) break;
                        Thread.Sleep(100);
                        Client.Tick();
                    }
                    if (Client.Network.CurrentSim.Region.Name.ToLower() == thisCamp.sim.ToLower())
                    {
                        debug("Seem to have arrived at camping sim succesfully", 4);
                        Client.Self.RequestSit(thisCamp.key, new LLVector3());
                        Client.Self.Sit();
                        for (int i = 0; i < 40; i++)
                        {
                            debug("Sitting on - " + Client.Self.SittingOn.ToString());
                            if (Client.Self.SittingOn != 0) break;
                            Thread.Sleep(250);
                            Client.Tick();
                        }
                        if (Client.Self.SittingOn != 0)
                        {
                            debug("Sucesfully sitting on camping target.", 5);
                            currentCamp = thisCamp.name;
                            campCheckTimer.Change(60000, 60000);
                            return true;
                        }
                        else
                        {
                            debug("Failed to sit on camping target.", 2);
                            return false;
                        }
                    }
                    else
                    {
                        debug("Failed to teleport to camping sim.", 2);
                        return false;
                    }
                }
            }
            debug("Camping spot not found", 1);
            return false;
        }
        campPosition getCamp(string name)
        {
            foreach (campPosition thisCamp in camps)
            {
                if (thisCamp.name == name)
                {
                    return thisCamp;
                }
            }
            return new campPosition();
        }
        string RPGWeather()
        {
            LLVector3 SunDirection = Client.Grid.SunDirection;
            //Console.WriteLine("Sun: " + SunDirection.X + " " + SunDirection.Y + " " + SunDirection.Z);
            string response = "";
            if (SunDirection.Z > 0.9) response = "It is midday";
            else if (SunDirection.Z > 0.5) response = "The sun is shining";
            else if (SunDirection.Z > 0.1)
            {
                if (SunDirection.X > 0) response = "It is still morning";
                else response = "It is late afternoon";
            }
            else if (SunDirection.Z > 0)
            {
                if (SunDirection.X > 0) response = "The sun is rising";
                else response = "The sun is setting";
            }
            else if (SunDirection.Z < -0.9) response = "It is the middle of the night";
            else if (SunDirection.Z < -0.5) response = "The moon lingers overhead";
            else if (SunDirection.Z < -0.1) response = "It is nighttime";
            else if (SunDirection.Z < 0)
            {
                if (SunDirection.X > 0) response = "It is not yet dawn";
                else response = "The night is still young";
            }
            return response + " in " + Client.Network.CurrentSim.Region.Name + ".";
        }
		string normalizeString(string[] message)
		{
			string result = null;
			int j = 0;
			for ( int i = 0 ; i < message.Length ; i++ ) {
				debug("Normalizing string - " + message[i] + " " + message[i] );
				if ( message[i] != null ) {
					if ( j > 0 ) {
						result += " ";
					}
					j++;
				}
				result += message[i];
			}
			debug("Normalized as " + result);
			return result;
		}
    }
}
